﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Data;
using System.Data.Common;
using MediSIIM.Message;
using MediSIIM.DBAccess;
using MediSIIM.Common;
using System.IO;
using TradeTest;

namespace SIIMWeb.YIBAO
{
    public class WebEngine
    {
        public dynamic baseBizComponent;

        public DBConnectionManager DBConnectionManager { get; set; }

        public int LoadAssembly(CallParam callparam)
        {
            int retCode = 0;

            Type type = null;
            Assembly ass;
            try
            {
                ass = Assembly.LoadFrom(callparam.BizDll);
                type = ass.GetType(callparam.ClassName, true, true);

            }
            catch (TypeLoadException typeEx)
            {
                return retCode = (int)ErrorDefine.LoadTypeError;
            }
            catch (Exception ex)
            {
                return retCode = (int)ErrorDefine.LoadAssemblyError;
            }

            try
            {
                this.baseBizComponent = Activator.CreateInstance(type, null);
            }
            catch (Exception ex)
            {
                return retCode = (int)ErrorDefine.CreateInstanceError;
            }

            return retCode;
        }

        public int RunService(SIIMMessage siimMsg, ref string outXml)
        {
            this.baseBizComponent.DBConnectionManager = DBConnectionManager;
            this.baseBizComponent.SIIMMessage = siimMsg;
            try
            {
                this.baseBizComponent.BizObjOut = GetOutObject();
                this.baseBizComponent.BizObjOut.Items[0].ERRNO = "0";
                this.baseBizComponent.PraseMessageIn();
                this.baseBizComponent.InitLoad();
                this.baseBizComponent.ProcessMessage(this.baseBizComponent.BizObjIn, this.baseBizComponent.BizObjOut);
                if (this.baseBizComponent.BizObjOut == null || this.baseBizComponent.BizObjOut.Items == null)
                {
                    throw new Exception("生成输出的XML为空");
                }
                outXml = this.baseBizComponent.BuildMessageOut();
            }
            catch (Exception ex)
            {
                if (this.baseBizComponent.BizObjOut.Items == null)
                {
                    this.baseBizComponent.BizObjOut = GetOutObject();
                }
                this.baseBizComponent.BizObjOut.Items[0].ERRNO = "-1";
                if (ex.InnerException == null)
                {
                    this.baseBizComponent.BizObjOut.Items[0].ERRMSG = ex.Message;
                }
                else
                {
                    this.baseBizComponent.BizObjOut.Items[0].ERRMSG = ex.InnerException.Message;
                }
                for (int i = 1; i < this.baseBizComponent.BizObjOut.Items.Length; i++)
                {
                    this.baseBizComponent.BizObjOut.Items[i] = null;
                }
                outXml = this.baseBizComponent.BuildMessageOut();
            }
            return 0;
        }

        private dynamic GetOutObject()
        {
            var outdateType = this.baseBizComponent.GetType().BaseType.GetGenericArguments()[1];
            dynamic outdata = outdateType.Assembly.CreateInstance(outdateType.Name);
            if (outdateType.GetProperty("Items").PropertyType.Name == "Object[]")
            {
                outdata.Items = new object[2];
                foreach (var attr in outdateType.GetProperty("Items").GetCustomAttributesData())
                {
                    if (attr.ConstructorArguments[0].Value.ToString() == "OUTMSG")
                    {
                        outdata.Items[0] = outdateType.Assembly.CreateInstance(attr.ConstructorArguments[1].Value.ToString());
                        break;
                    }
                }
            }
            else
            {
                object array = new object();
                outdata.Items = outdateType.GetProperty("Items").PropertyType.InvokeMember("Set", BindingFlags.CreateInstance, null, array, new object[] { 1 });
                var item = outdateType.Assembly.CreateInstance(outdateType.GetProperty("Items").PropertyType.Name.Replace("[]", string.Empty));
                outdateType.GetProperty("Items").PropertyType.GetMethod("SetValue", new Type[2] { item.GetType(), typeof(int) }).Invoke(outdata.Items, new object[] { item, 0 });
            }
            return outdata;
        }
    }
}
